/*
 * @Author: 李无敌
 * @Date: 2025-07-25 13:57:38
 * @LastEditors: 李无敌
 * @LastEditTime: 2025-08-08 08:47:51
 * @FilePath: \nest-base\src\main.ts
 */
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
const fastifyHelmet = require('@fastify/helmet');
const fastifyCompress = require('@fastify/compress');
const fastifyCookie = require('@fastify/cookie');
import fastifyMultipart from '@fastify/multipart';
const fastifyStatic = require('@fastify/static');
import { join } from 'path';

import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
import { ApiDocsController } from './controllers/api-docs.controller';
import { CSPHelper } from './common/utils/csp-helper';
import { cspReportPlugin } from './common/plugins/csp-report.plugin';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );
  const configService = app.get(ConfigService);
  const port = configService.get('app.port', 7001);
  const host = configService.get('app.host', '0.0.0.0');

  // // 注册Fastify插件
  const securityConfig = configService.get('security');
  
  // 根据配置决定是否启用CSP
  const helmetConfig: any = {};
  
  if (securityConfig.csp?.enabled) {
    helmetConfig.contentSecurityPolicy = {
      directives: securityConfig.csp.directives,
      reportOnly: securityConfig.csp.reportOnly
    };
  } else {
    helmetConfig.contentSecurityPolicy = false;
  }
  
  // 配置跨域策略
  if (securityConfig.csp?.crossOrigin) {
    const crossOrigin = securityConfig.csp.crossOrigin;
    if (crossOrigin.embedderPolicy !== undefined) {
      helmetConfig.crossOriginEmbedderPolicy = crossOrigin.embedderPolicy;
    }
    if (crossOrigin.openerPolicy) {
      helmetConfig.crossOriginOpenerPolicy = { policy: crossOrigin.openerPolicy };
    }
    if (crossOrigin.resourcePolicy) {
      helmetConfig.crossOriginResourcePolicy = { policy: crossOrigin.resourcePolicy };
    }
  }
  
  // 配置引用策略
  if (securityConfig.csp?.referrerPolicy) {
    helmetConfig.referrerPolicy = { policy: securityConfig.csp.referrerPolicy };
  }
  
  // 验证CSP配置
  if (securityConfig.csp?.enabled) {
    const validation = CSPHelper.validateCSPConfig(securityConfig.csp);
    if (!validation.valid) {
      console.warn('⚠️  CSP配置验证失败:', validation.errors);
    }
    
    // 检查CSP安全级别
    const securityLevel = CSPHelper.checkCSPSecurityLevel(securityConfig.csp);
    console.log(`🔒 CSP安全级别: ${securityLevel.level}`);
    if (securityLevel.warnings.length > 0) {
      console.warn('⚠️  CSP安全警告:', securityLevel.warnings);
    }
    
    // 输出CSP配置信息
    if (securityConfig.csp.reportOnly) {
      console.log('📊 CSP模式: 仅报告 (不会阻止违规内容)');
    } else {
      console.log('🛡️  CSP模式: 强制执行');
    }
  } else {
    console.log('⚠️  CSP未启用');
  }
  
  await app.register(fastifyHelmet, helmetConfig);
  await app.register(fastifyCompress);
  await app.register(fastifyCookie);
  
  // 注册CSP报告插件
  await app.register(cspReportPlugin as any);
  // 文件上传配置
  const uploadConfig = configService.get('upload');
  await app.register(fastifyMultipart as any, {
    limits: {
      fileSize: uploadConfig.maxSize, // 从配置文件读取文件大小限制
      files: uploadConfig.maxFiles, // 从配置文件读取文件数量限制
    },
  });

  // 注册静态文件服务 - 为uploads目录提供静态资源访问
  const staticConfig = uploadConfig.static;
  await app.register(fastifyStatic, {
    root: join(process.cwd(), staticConfig.path),
    prefix: staticConfig.prefix,
    decorateReply: staticConfig.decorateReply,
  });

  // CORS配置
  const corsOrigins = configService.get('security.cors.origin', '*');
  const corsCredentials = configService.get('security.cors.credentials', true);
  
  // 获取本机IP地址
  const networkInterfaces = require('os').networkInterfaces();
  
  app.enableCors({
    origin: corsOrigins,
    credentials: corsCredentials,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
    exposedHeaders: ['Content-Disposition'],
  });

  // // 全局前缀
  // app.setGlobalPrefix('api');

  // 全局管道
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: false, // 允许额外参数
      transform: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );

  // 全局过滤器
  app.useGlobalFilters(new HttpExceptionFilter());

  // 全局拦截器
  app.useGlobalInterceptors(new TransformInterceptor());

  // Swagger配置
  const swaggerConfigBuilder = new DocumentBuilder()
    .setTitle(configService.get('swagger.title', 'NestJS Base API'))
    .setDescription(configService.get('swagger.description', '企业级NestJS权限管理系统API文档') +  `       \nJSON格式：http://localhost:${port}/api-docs/json`)
    .setVersion(configService.get('swagger.version', '1.0.0'))
    .addBearerAuth()

  
  // 动态添加所有可用的IP地址
  const ipAddressList = [];
  for (const name of Object.keys(networkInterfaces)) {
    if (name !== '以太网') break;
    for (const iface of networkInterfaces[name]) {
      if (iface.family === 'IPv4' && !iface.internal) {
        ipAddressList.push(iface.address);
      }
    }
  }
  
  const swaggerConfig = swaggerConfigBuilder.build();
  const document = SwaggerModule.createDocument(app, swaggerConfig);
  
  // 配置Swagger UI，允许通过IP访问
  SwaggerModule.setup(
    configService.get('swagger.path', 'api-docs'),
    app,
    document,
    {
      customSiteTitle: 'NestJS Base API Docs',
      swaggerOptions: {
        docExpansion: 'list',
        filter: true,
        showRequestDuration: true,
        // 禁用Swagger的主机验证，允许任何主机访问
        validatorUrl: null,
      },
      // 不使用外部CDN资源，使用本地资源
    },
  );

  // 设置API文档控制器
  const apiDocsController = app.get(ApiDocsController);
  apiDocsController.setApp(app);

  // 启动应用
  await app.listen(port, host);
  
  // 显示所有可用的网络IP地址
  ipAddressList.forEach(ip => {
    console.log(`网络IP访问: http://${ip}:${port}`);
  });
  
  if (ipAddressList.length === 0) {
    console.log('⚠️  未检测到可用的网络IP地址，可能需要检查网络配置');
  }
  
  // 添加所有IP地址的Swagger访问链接
  ipAddressList.forEach(ip => {
    console.log(`📚 API文档 (IP): http://${ip}:${port}/${configService.get('swagger.path', 'api-docs')}`);
  });
  
  // 显示API文档访问地址
  ipAddressList.forEach(ip => {
    console.log(`   JSON格式 (IP): http://${ip}:${port}/api-docs/json`);
    console.log(`   YAML格式 (IP): http://${ip}:${port}/api-docs/yaml`);
  });
  console.log(`🌍 环境: ${configService.get('app.env', 'development')}`);
}

bootstrap().catch((error) => {
  console.error('应用启动失败:', error);
  process.exit(1);
});
